/*
    DIMVisual-KAAPI, the DIMVisual bundle for KAAPI trace files
    Copyright (c) 2008 Lucas Mello Schnorr <schnorr@gmail.com>

    This file is part of DIMVisual-KAAPI.

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "KAAPIFileReader.h"

@implementation KAAPIFileReader (Search)
- (void) searchTicksPerSecond
{
	GEvent *e;
	GName *name;

	//search in buffer
	unsigned int i;
	for (i = 0; i < [buf count]; i++){
		e = (GEvent *)[buf objectAtIndex: i];
		name = [e name];
		if ([[name description] isEqual: @"EVT_UTIL_PROCESS_INFO"]){
			GFields *f = [e fields];
			ticksPerSecond = [[f fieldWithSimpleStringKey: @"tick_per_s"] doubleValue];
		
			timeOfDayEV = [[f fieldWithSimpleStringKey: @"timeofday"] doubleValue]; 
			tickEV = [[[e timestamp] description] doubleValue];
			break;
		}
	}

	while (ticksPerSecond == 0){ //ok, did not found in buffer
		e = [self read];
		if (e == nil){
			break;
		}
		[buf addObject: e];

		name = [e name];
		if ([[name description] isEqual: @"EVT_UTIL_PROCESS_INFO"]){
			GFields *f = [e fields];
			ticksPerSecond = [[f fieldWithSimpleStringKey: @"tick_per_s"] doubleValue];
		
			timeOfDayEV = [[f fieldWithSimpleStringKey: @"timeofday"] doubleValue]; 
			tickEV = [[[e timestamp] description] doubleValue];
			break;
		}
	}
	if (ticksPerSecond == 0){
		NSString *str = [NSString stringWithFormat: @"KAAPIFileReader (%@): file %@ does not have an event of type Event::EVT_UTIL_PROCESS_INFO (level=%d,event=%d) as expected by the dimvisual-kaapi module.", self, traceFilename, Event::TR_UTIL_LEVEL, Event::UTIL_PROCESS_INFO];
		[[NSException exceptionWithName: @"DIMVisual-KAAPIFileReader" reason: str userInfo: nil] raise];
	}
}

- (void) searchHostnameAndDefineSync
{
	GEvent *e;
	GName *name;

	//search in buffer
	unsigned int i;
	for (i = 0; i < [buf count]; i++){
		e = (GEvent *)[buf objectAtIndex: i];
		name = [e name];
		if ([[name description] isEqual: @"EVT_UTIL_PROCESS_NAME"]){
			int x, i;
			GFields *f = [e fields];
			NSMutableString *h = [NSMutableString string];
			x = [[f fieldWithSimpleStringKey: @"csize"] intValue];
			for (i = 0; i < (x + 31)/32; i++){
				GEvent *bloc = [self read];
				GFields *blocf = [bloc fields];
				NSString *str;
				str = [blocf fieldWithSimpleStringKey: @"name"];
				[h appendString: str];
				[buf addObject: bloc];
			}
			hostname = h;
			[hostname retain];
			sync = [syncs objectForKey: hostname];
			break;
		}
	}

	while (hostname == nil){
		e = [self read];
		if (e == nil){
			break;
		}
		[buf addObject: e];

		name = [e name];
		if ([[name description] isEqual: @"EVT_UTIL_PROCESS_NAME"]){
			int x, i;
			GFields *f = [e fields];
			NSMutableString *h = [NSMutableString string];
			x = [[f fieldWithSimpleStringKey: @"csize"] intValue];
			for (i = 0; i < (x + 31)/32; i++){
				GEvent *bloc = [self read];
				GFields *blocf = [bloc fields];
				NSString *str;
				str = [blocf fieldWithSimpleStringKey: @"name"];
				[h appendString: str];
				[buf addObject: bloc];
			}
			hostname = h;
			[hostname retain];
			sync = [syncs objectForKey: hostname];
			break;
		}
	}
	if (hostname == nil){
		NSString *str = [NSString stringWithFormat: @"KAAPIFileReader (%@): file %@ does not have an event of type Event::EVT_UTIL_PROCESS_NAME as expected by the dimvisual-kaapi module.", self, traceFilename];
		[[NSException exceptionWithName: @"DIMVisual-KAAPIFileReader" reason: str userInfo: nil] raise];
	}
}

- (void) defineTimestampForEvent: (GEvent *) e
{
	if (ticksPerSecond != 0 && timeOfDayEV != 0 && tickEV != 0){
		double thistick = [[[e timestamp] description] doubleValue];
		double ntev = ((thistick - tickEV)/ticksPerSecond)+timeOfDayEV;
		GTimestamp *t = [[GTimestamp alloc] init];
		[t setTimestamp:[NSString stringWithFormat:@"%f",ntev]];
		[e setTimestamp: t];
		[t release];
	}
}

- (void) defineHostnameForEvent: (GEvent *) e
{
	if (hostname != nil){
		GFields *f = [e fields];
		NSString *value5 = [NSString stringWithFormat: @"%@", hostname];
		[f setFieldWithStringKey: @"hostname" withValue: value5];
	}
}

- (void) synchronizeEvent: (GEvent *) e
{
	if (sync != nil){
		NSString *oldtime = [[e timestamp] description];
		double oldtimed = [oldtime doubleValue];
		oldtimed = oldtimed * 1000000;
		NSString *newtime = [sync correctTime: [NSString stringWithFormat: @"%.0f", oldtimed]];
		double newtimed = [newtime doubleValue];
		newtimed = newtimed / 1000000;
		newtime = [NSString stringWithFormat: @"%f", newtimed];
		GTimestamp *timestamp = [[GTimestamp alloc] init];
		[timestamp setTimestamp: newtime];
		[e setTimestamp: timestamp];
		[timestamp release];
	}
}

- (void) consumeThreadNameEventsFromBuffer
{
	GEvent *e;
	GName *name;
	unsigned int i;

	for (i = 0; i < [buf count]; i++){
		e = (GEvent *)[buf objectAtIndex: i];
		name = [e name];
		if ([[name description] isEqual: @"EVT_UTIL_THREAD_NAME"]){
			GFields *f = [e fields];
			NSString *threadName, *cid;
			threadName = [f fieldWithSimpleStringKey: @"name"];
			cid = [f fieldWithSimpleStringKey: @"cid"];
			[threadNames setObject: threadName forKey: cid]; 
			[buf removeObjectAtIndex: i];
			i--;
		}
	}
}
@end
